home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Applications / QuArK / quarkpy / mdlhandles.py < prev    next >
Text File  |  2004-01-05  |  14KB  |  447 lines

  1. """   QuArK  -  Quake Army Knife
  2.  
  3. Model editor mouse handles.
  4. """
  5. #
  6. # Copyright (C) 1996-99 Armin Rigo
  7. # THIS FILE IS PROTECTED BY THE GNU GENERAL PUBLIC LICENCE
  8. # FOUND IN FILE "COPYING.TXT"
  9. #
  10.  
  11. #$Header: /cvsroot/quark/runtime/quarkpy/mdlhandles.py,v 1.8 2001/03/15 21:07:49 aiv Exp $
  12.  
  13.  
  14.  
  15. #
  16. # See comments in maphandles.py.
  17. #
  18.  
  19.  
  20. import quarkx
  21. import math
  22. from qdictionnary import Strings
  23. import qhandles
  24. from mdlutils import *
  25. import mdlentities
  26. import qmenu
  27.  
  28.  
  29.  
  30. vertexdotcolor = 0
  31.  
  32.  
  33. #
  34. # The handle classes.
  35. #
  36.  
  37. class CenterHandle(qhandles.CenterHandle):
  38.     "Like qhandles.CenterHandle, but specifically for the Model editor."
  39.     def menu(self, editor, view):
  40.         return mdlentities.CallManager("menu", self.centerof, editor) + self.OriginItems(editor, view)
  41.  
  42. class IconHandle(qhandles.IconHandle):
  43.     "Like qhandles.IconHandle, but specifically for the Model editor."
  44.     def menu(self, editor, view):
  45.         return mdlentities.CallManager("menu", self.centerof, editor) + self.OriginItems(editor, view)
  46.  
  47.  
  48. class MdlEyeDirection(qhandles.EyeDirection):
  49.  
  50.     MODE = SS_MODEL
  51.  
  52.  
  53.  
  54. class VertexHandle(qhandles.GenericHandle):
  55.     "Frame Vertex handle."
  56.  
  57.     size = (3,3)
  58.  
  59.     def __init__(self, pos):
  60.         qhandles.GenericHandle.__init__(self, pos)
  61.         self.cursor = CR_CROSSH
  62.  
  63.     def menu(self, editor, view):
  64.         def forcegrid1click(m, self=self, editor=editor, view=view):
  65.             self.Action(editor, self.pos, self.pos, MB_CTRL, view, Strings[560])
  66.         def addhere1click(m, self=self, editor=editor, view=view):
  67.             addvertex(editor.Root.currentcomponent, self.pos)
  68.         def removevertex1click(m, self=self, editor=editor, view=view):
  69.             removevertex(editor.Root.currentcomponent, self.index)
  70.     def pick_vertex(m, self=self, editor=editor, view=view):
  71.         if self.index not in editor.picked:
  72.               editor.picked = editor.picked + [ self.index ]
  73.             else:
  74.               editor.picked.remove(self.index)
  75.               
  76.         return [qmenu.item("&Add Vertex Here", addhere1click, "add vertex to component"),
  77.                 qmenu.item("&Remove Vertex", removevertex1click, "removes a vertex from the component"),
  78.                 qmenu.item("&Pick Vertex", pick_vertex, "picks a vertex for creating triangles"),
  79.                 qmenu.sep,
  80.                 qmenu.item("&Force to grid", forcegrid1click,"force vertex to grid")] + self.OriginItems(editor, view)
  81.  
  82.     def draw(self, view, cv, draghandle=None):
  83.         p = view.proj(self.pos)
  84.         if p.visible:
  85.             cv.setpixel(p.x, p.y, vertexdotcolor)
  86.             editor = mapeditor()
  87.             if editor is not None:
  88.               if self.index in editor.picked:
  89.                 cv.pencolor = WHITE
  90.                 cv.rectangle(p.x-3, p.y-3, p.x+3, p.y+3)
  91.  
  92.     def drag(self, v1, v2, flags, view):
  93.         p0 = view.proj(self.pos)
  94.         if not p0.visible: return
  95.         if flags&MB_CTRL:
  96.           v2 = qhandles.aligntogrid(v2, 0)
  97.         delta = v2-v1
  98.         editor = mapeditor()
  99.         if editor is not None:
  100.           if editor.lock_x==1:
  101.             delta = quarkx.vect(0, delta.y, delta.z)
  102.           if editor.lock_y==1:
  103.             delta = quarkx.vect(delta.x, 0, delta.z)
  104.           if editor.lock_z==1:
  105.             delta = quarkx.vect(delta.x, delta.y, 0)
  106.         self.draghint = vtohint(delta)
  107.         new = self.frame.copy()
  108.         if delta or (flags&MB_REDIMAGE):
  109.           vtxs = new.vertices
  110.           vtxs[self.index] = vtxs[self.index] + delta
  111.           new.vertices = vtxs
  112.         return [self.frame], [new]
  113.  
  114.  
  115. class SkinHandle(qhandles.GenericHandle):
  116.   "Skin Handle for s / t positioning"
  117.  
  118.   size = (3,3)
  119.  
  120.   def __init__(self, pos, tri_index, ver_index, comp):
  121.       qhandles.GenericHandle.__init__(self, pos)
  122.       self.cursor = CR_CROSSH
  123.       self.tri_index = tri_index
  124.       self.ver_index = ver_index
  125.       self.component = comp
  126.  
  127. #  def drag(self, v1, v2, flags, view):
  128. #      p0 = view.proj(self.pos)
  129. #      if not p0.visible: return
  130. #      if flags&MB_CTRL:
  131. #        v2 = qhandles.aligntogrid(v2, 0)
  132. #      delta = v2-v1
  133. #      editor = mapeditor()
  134. #      if editor is not None:
  135. #        if editor.lock_x==1:
  136. #          delta = quarkx.vect(0, delta.y, 0)
  137. #        if editor.lock_y==1:
  138. #          delta = quarkx.vect(delta.x, 0, 0)
  139. #      self.draghint = "moving s/t vertex: " + ftoss(delta.x) + ", " + ftoss(delta.y)
  140. #      new = self.component.copy()
  141. #      if delta or (flags&MB_REDIMAGE):
  142. #        tris = new.triangles
  143. #
  144. #        oldtri = tris[self.tri_index]
  145. #        oldvert = oldtri[self.ver_index]
  146. #        newvert = [oldvert[0], oldvert[1]+delta.x, oldvert[2]+delta.y]        
  147. #        if (self.ver_index == 0):
  148. #          newtri = [newvert, oldtri[1], oldtri[2]]
  149. #        elif (self.ver_index == 1):
  150. #          newtri = [oldtri[0], newvert, oldtri[2]]
  151. #        elif (self.ver_index == 2):
  152. #          newtri = [oldtri[0], oldtri[1], newvert]
  153. #        tris[self.tri_index] = newtri
  154. #
  155. #        new.triangles = tris
  156. #      return [self.component], [new]
  157.   
  158.   def draw(self, view, cv, draghandle=None):
  159.       p = view.proj(self.pos)
  160.       if p.visible:
  161.           cv.setpixel(p.x, p.y, vertexdotcolor)
  162.  
  163. class BoneHandle(qhandles.GenericHandle):
  164.   "Bone Handle"
  165.  
  166.   size = (3,3)
  167.   def __init__(self, pos):
  168.       qhandles.GenericHandle.__init__(self, pos)
  169.       self.cursor = CR_CROSSH
  170.  
  171.   def drag(self, v1, v2, flags, view):
  172.       p0 = view.proj(self.pos)
  173.       if not p0.visible: return
  174.       if flags&MB_CTRL:
  175.         v2 = qhandles.aligntogrid(v2, 0)
  176.       delta = v2-v1
  177.       editor = mapeditor()
  178.       if editor is not None:
  179.         if editor.lock_x==1:
  180.           delta = quarkx.vect(0, delta.y, delta.z)
  181.         if editor.lock_y==1:
  182.           delta = quarkx.vect(delta.x, 0, delta.z)
  183.         if editor.lock_z==1:
  184.           delta = quarkx.vect(delta.x, delta.y, 0)
  185.       self.draghint = vtohint(delta)
  186.       new = self.bone.copy()
  187.       if delta or (flags&MB_REDIMAGE):
  188.         if (self.s_or_e == 0):
  189.           apoint = self.bone.start_point
  190.           apoint = apoint + delta
  191.           new.start_point = apoint
  192.         else:
  193.           apoint = self.bone.end_point
  194.           debug(str(self.bone.bone_length))
  195.           if self.bone["length_locked"]=="1":
  196.             apoint = ProjectKeepingLength(
  197.                         self.bone.start_point,
  198.                         self.bone.end_point + delta,
  199.                         self.bone.bone_length
  200.                      )
  201.           else:
  202.             apoint = apoint + delta
  203.           new.end_offset = apoint - self.bone.start_point
  204.       return [self.bone], [new]
  205.  
  206.   def draw(self, view, cv, draghandle=None):
  207.       p = view.proj(self.pos)
  208.       if p is None:
  209.         return
  210.       if p.visible:
  211.           cv.brushcolor = WHITE
  212.           cv.ellipse(p.x - 3, p.y - 3, p.x + 3, p.y + 3)
  213.  
  214. def skinzoom(view, center=None):
  215.     if center is None:
  216.         center = view.screencenter
  217.     view.setprojmode("2D", view.info["matrix"]*view.info["scale"], 0)
  218.     bmin, bmax = view.info["bbox"]
  219.     x1=y1=x2=y2=None
  220.     for x in (bmin.x,bmax.x):   # all 8 corners of the bounding box
  221.         for y in (bmin.y,bmax.y):
  222.             for z in (bmin.z,bmax.z):
  223.                 p = view.proj(x,y,z)
  224.                 if (x1 is None) or (p.x<x1): x1=p.x
  225.                 if (y1 is None) or (p.y<y1): y1=p.y
  226.                 if (x2 is None) or (p.x>x2): x2=p.x
  227.                 if (y2 is None) or (p.y>y2): y2=p.y
  228.     view.setrange(x2-x1+36, y2-y1+34, 0.5*(bmin+bmax))
  229.  
  230.      # trick : if we are far enough and scroll bars are hidden,
  231.      # the code below clamb the position of "center" so that
  232.      # the picture is completely inside the view.
  233.     x1=y1=x2=y2=None
  234.     for x in (bmin.x,bmax.x):   # all 8 corners of the bounding box
  235.         for y in (bmin.y,bmax.y):
  236.             for z in (bmin.z,bmax.z):
  237.                 p = view.proj(x,y,z)    # re-proj... because of setrange
  238.                 if (x1 is None) or (p.x<x1): x1=p.x
  239.                 if (y1 is None) or (p.y<y1): y1=p.y
  240.                 if (x2 is None) or (p.x>x2): x2=p.x
  241.                 if (y2 is None) or (p.y>y2): y2=p.y
  242.     w,h = view.clientarea
  243.     w,h = (w-36)/2, (h-34)/2
  244.     x,y,z = view.proj(center).tuple
  245.     t1,t2 = x2-w,x1+w
  246.     if t2>=t1:
  247.         if x<t1: x=t1
  248.         elif x>t2: x=t2
  249.     t1,t2 = y2-h,y1+h
  250.     if t2>=t1:
  251.         if y<t1: y=t1
  252.         elif y>t2: y=t2
  253.     view.screencenter = view.space(x,y,z)
  254.     p = view.proj(view.info["origin"])
  255.     view.depth = (p.z-0.1, p.z+100.0)
  256.  
  257. def buildskinvertices(editor, view, component):
  258.     "builds a list of handles to display on the skinview"
  259.  
  260.     def drawsingleskin(view, component=component, editor=editor):
  261.         view.color = BLACK
  262.         view.drawmap(component.skindrawobject)
  263. #        view.solidimage(component.currentskin)
  264.         view.drawmap(component.skindrawobject, DM_REDRAWFACES|DM_OTHERCOLOR, 0x2584C9)   # draw the face contour
  265.         editor.finishdrawing(view)
  266.         # end of drawsingleskin
  267.  
  268.     h = [ ]  
  269.     tris = component.triangles
  270.     for i in range(len(tris)):
  271.         tri = tris[i]
  272.         for j in range(len(tri)):
  273.             vtx = tri[j]
  274.             h.append(SkinHandle(quarkx.vect(vtx[1], vtx[2], 0), i, j, component))
  275. #    n = quarkx.vect(1,1,1) 
  276. #    v = orthogonalvect(n, view)
  277.     org = component.originst
  278.     view.handles = qhandles.FilterHandles(h, SS_MODEL)
  279.     view.flags = view.flags &~ (MV_HSCROLLBAR | MV_VSCROLLBAR)
  280.     view.viewmode = "tex"
  281.     view.info = {"type": "2D",                  
  282.                  "matrix": matrix_rot_z(pi2),
  283.                  "origin": org,
  284.                  "scale": 1,
  285.                  "custom": skinzoom,
  286.                  "bbox": quarkx.boundingboxof(map(lambda h: h.pos, view.handles)),
  287.                  "noclick": None,
  288.                  "mousemode": None
  289.                  }
  290.     skinzoom(view, org)
  291.     view.flags = view.flags | qhandles.vfSkinView;
  292.     editor.setupview(view, drawsingleskin, 0)
  293.     
  294.       
  295. #
  296. # Functions to build common lists of handles.
  297. #
  298.  
  299. def BuildCommonHandles(editor, ex):
  300.     "Build a list of handles to display on all map views."
  301.  
  302.     fs = ex.uniquesel
  303.     if (fs is None) or editor.linearbox:
  304.         return []
  305.     else:
  306.         #
  307.         # Get the list of handles from the entity manager.
  308.         #
  309.         return mdlentities.CallManager("handlesopt", fs, editor)
  310.  
  311.  
  312.  
  313. def BuildHandles(editor, ex, view):
  314.     "Build a list of handles to display on one map view."
  315.  
  316.     fs = ex.uniquesel
  317.     if (fs is None) or editor.linearbox:
  318.         #
  319.         # Display a linear mapping box.
  320.         #
  321.         list = ex.sellist
  322.         box = quarkx.boundingboxof(list)
  323.         if box is None:
  324.             h = []
  325.         else:
  326.             manager = qhandles.LinHandlesManager(MapColor("Linear"), box, list)
  327.             h = manager.BuildHandles(editor.interestingpoint())
  328.         h = qhandles.FilterHandles(h, SS_MODEL)
  329.     else:
  330.         #
  331.         # Get the list of handles from the entity manager.
  332.         #
  333.         h = mdlentities.CallManager("handles", fs, editor, view)
  334.     #
  335.     # The 3D view "eyes".
  336.     #
  337.     for v in editor.layout.views:
  338.         if (v is not view) and (v.info["type"] == "3D"):
  339.             h.append(qhandles.EyePosition(view, v))
  340.             h.append(MdlEyeDirection(view, v))
  341.     return qhandles.FilterHandles(h, SS_MODEL)
  342.  
  343.  
  344.  
  345. #
  346. # Drag Objects
  347. #
  348.  
  349. class RectSelDragObject(qhandles.RectangleDragObject):
  350.     "A red rectangle that selects the polyhedrons it touches."
  351.  
  352.     def rectanglesel(self, editor, x,y, rectangle):
  353.         if not ("T" in self.todo):
  354.             editor.layout.explorer.uniquesel = None
  355.         polylist = editor.Root.findallsubitems("", ":p")
  356.         lastsel = None
  357.         for p in polylist:
  358.             if rectangle.intersects(p):
  359.                 p.selected = 1
  360.                 lastsel = p
  361.         if lastsel is not None:
  362.             editor.layout.explorer.focus = lastsel
  363.             editor.layout.explorer.selchanged()
  364.  
  365.  
  366. #
  367. # Mouse Clicking and Dragging on map views.
  368. #
  369.  
  370. def MouseDragging(self, view, x, y, s, handle):
  371.     "Mouse Drag on a Model View."
  372.  
  373.     #
  374.     # qhandles.MouseDragging builds the DragObject.
  375.     #
  376.  
  377.     if handle is not None:
  378.         s = handle.click(self)
  379.         if s and ("S" in s):
  380.             self.layout.actionmpp()  # update the multi-pages-panel
  381.  
  382.     return qhandles.MouseDragging(self, view, x, y, s, handle, MapColor("GrayImage", SS_MODEL))
  383.  
  384.  
  385. def MouseClicked(self, view, x, y, s, handle):
  386.     "Mouse Click on a Model view."
  387.  
  388.     #
  389.     # qhandles.MouseClicked manages the click but doesn't actually select anything
  390.     #
  391.  
  392.     flags = qhandles.MouseClicked(self, view, x, y, s, handle)
  393.  
  394.     if "1" in flags:
  395.  
  396.         #
  397.         # This mouse click must select something.
  398.         #
  399.  
  400.         self.layout.setupdepth(view)
  401.         choice = view.clicktarget(self.Root, x, y)
  402.          # this is the list of frame triangles we clicked on
  403.         if len(choice):
  404.             choice.sort()   # list of (clickpoint,component,triangleindex) tuples - sort by depth
  405.             clickpoint, obj, tridx = choice[0]
  406.             if (obj.type != ':mc') or (type(tridx) is not type(0)):   # should not occur
  407.                 return flags
  408.             if ("M" in s) and obj.selected:    # if Menu, we try to keep the currently selected objects
  409.                 return flags
  410.           # if "T" in s:    # if Multiple selection request
  411.           #     obj.togglesel()
  412.           #     if obj.selected:
  413.           #         self.layout.explorer.focus = obj
  414.           #     self.layout.explorer.selchanged()
  415.           # else:
  416.           #     ...
  417.           #     self.layout.explorer.uniquesel = obj
  418.         else:
  419.             if not ("T" in s):    # clear current selection
  420.                 self.layout.explorer.uniquesel = None
  421.         return flags+"S"
  422.     return flags
  423.  
  424. # ----------- REVISION HISTORY ------------
  425. #
  426. #
  427. #$Log: mdlhandles.py,v $
  428. #Revision 1.8  2001/03/15 21:07:49  aiv
  429. #fixed bugs found by fpbrowser
  430. #
  431. #Revision 1.7  2001/02/07 18:40:47  aiv
  432. #bezier texture vertice page started.
  433. #
  434. #Revision 1.6  2001/02/05 20:03:12  aiv
  435. #Fixed stupid bug when displaying texture vertices
  436. #
  437. #Revision 1.5  2000/10/11 19:07:47  aiv
  438. #Bones, and some kinda skin vertice viewer
  439. #
  440. #Revision 1.4  2000/08/21 21:33:04  aiv
  441. #Misc. Changes / bugfixes
  442. #
  443. #Revision 1.2  2000/06/02 16:00:22  alexander
  444. #added cvs headers
  445. #
  446. #
  447. #